package com.xbongbong.paas.service.impl;


import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.help.EsignHelp;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.service.EsignService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.menu.enums.SystemAppMenuEnum;
import com.xbongbong.pro.esign.pojo.EsignFilePojo;
import com.xbongbong.pro.esign.pojo.dto.EsignCorpRealnameDTO;
import com.xbongbong.pro.esign.pojo.dto.EsignFlowDetailDTO;
import com.xbongbong.pro.esign.pojo.dto.EsignFlowStatusDTO;
import com.xbongbong.pro.esign.pojo.dto.EsignGetSwitchDTO;
import com.xbongbong.pro.esign.pojo.dto.EsignPreCheckDTO;
import com.xbongbong.pro.esign.pojo.dto.EsignProcessStartDTO;
import com.xbongbong.pro.esign.pojo.dto.EsignSetSwitchDTO;
import com.xbongbong.pro.esign.pojo.dto.HasEsignDTO;
import com.xbongbong.pro.esign.pojo.dto.XbbFileDetailDTO;
import com.xbongbong.pro.esign.pojo.dto.XbbProcessStartDTO;
import com.xbongbong.pro.esign.pojo.dto.XbbSignNoticeUrlDTO;
import com.xbongbong.pro.esign.pojo.vo.EsignContractMarginVO;
import com.xbongbong.pro.esign.pojo.vo.EsignCorpConsoleVO;
import com.xbongbong.pro.esign.pojo.vo.EsignCorpInfoVO;
import com.xbongbong.pro.esign.pojo.vo.EsignCorpRealnameVO;
import com.xbongbong.pro.esign.pojo.vo.EsignFileDetailVO;
import com.xbongbong.pro.esign.pojo.vo.EsignFlowDetailVO;
import com.xbongbong.pro.esign.pojo.vo.EsignFlowStatusVO;
import com.xbongbong.pro.esign.pojo.vo.EsignGetSwitchVO;
import com.xbongbong.pro.esign.pojo.vo.EsignNoticeUrlVO;
import com.xbongbong.pro.esign.pojo.vo.EsignPreCheckVO;
import com.xbongbong.pro.esign.pojo.vo.EsignProcessStartVO;
import com.xbongbong.pro.esign.pojo.vo.HasEsignVO;
import com.xbongbong.pro.esign.pojo.vo.RemindVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.entity.EsignSetEntity;
import com.xbongbong.saas.domain.entity.EsignTaskEntity;
import com.xbongbong.saas.enums.EsignFlowStatusEnum;
import com.xbongbong.saas.enums.EsignRemindEnum;
import com.xbongbong.saas.enums.EsignTaskTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.ContractModel;
import com.xbongbong.saas.model.EsignSetModel;
import com.xbongbong.saas.model.EsignTaskModel;
import com.xbongbong.saas.model.PaasFormDataModel;
import com.xbongbong.saas.model.PurchaseModel;
import com.xbongbong.saas.model.QuotationModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 *
 * 创建时间 2020/6/18 10:09 AM
 * 修改时间 2020/6/18 10:09 AM
 * @author chy
 */
@Service("esignService")
public class EsignServiceImpl implements EsignService {

    private static final Logger LOG = LoggerFactory.getLogger(EsignServiceImpl.class);

    private static final Integer WARNING_COUNT = 20;

    @Resource
    private EsignHelp esignHelp;
    @Resource
    private EsignSetModel esignSetModel;
    @Resource
    private EsignTaskModel esignTaskModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private ContractModel contractModel;
    @Resource
    private PurchaseModel purchaseModel;
    @Resource
    private QuotationModel quotationModel;
    @Resource
    private PaasFormDataModel paasFormDataModel;

    @Override
    public RemindVO remind(BaseDTO baseDTO) throws XbbException {
        RemindVO remindVO = new RemindVO();
        String corpid = baseDTO.getCorpid();
        PaasAppEntity paasAppEntity = paasAppModel.getByAlias(SystemAppMenuEnum.ESIGN.getAlias(), corpid);

        //应用未开启
        if (Objects.isNull(paasAppEntity) || !Objects.equals(paasAppEntity.getEnable(), BasicConstant.ONE)) {
            return remindVO;
        }

        //企业未实名（仅提醒管理员）
        UserVO userVO = baseDTO.getLoginUser();
        if (userVO.isAdminOrBoss()) {
            EsignCorpInfoVO esignCorpInfoVO = getEsignCorpInfo(corpid);
            if (!esignCorpInfoVO.getIsRealName()) {
                remindVO.setContent(EsignRemindEnum.CORP_NO_REALNAME.getContent());
                remindVO.setUrl(EsignRemindEnum.CORP_NO_REALNAME.getUrl());
                return remindVO;
            }
        }

        EsignContractMarginVO esignContractMarginVO = getEsignContractMargin(corpid);

        if (Objects.equals(esignContractMarginVO.getCount(), 0)) {
            //电子合同余额为0，点击这里去充值。（管理员）
            if (userVO.isAdminOrBoss()) {
                remindVO.setContent(EsignRemindEnum.BALANCE_EMPTY_FOR_ADMIN.getContent());
                remindVO.setUrl(EsignRemindEnum.BALANCE_EMPTY_FOR_ADMIN.getUrl());
                return remindVO;
            } else {
                //电子合同余额为0，请联系管理员及时充值。
                remindVO.setContent(EsignRemindEnum.BALANCE_EMPTY_FOR_STAFF.getContent());
                return remindVO;
            }
        }

        if (esignContractMarginVO.getCount() < WARNING_COUNT) {
            //电子合同余额不足20份，点击这里去充值。（管理员）
            if (userVO.isAdminOrBoss()) {
                remindVO.setContent(EsignRemindEnum.BALANCE_WARNING_FOR_ADMIN.getContent());
                remindVO.setUrl(EsignRemindEnum.BALANCE_WARNING_FOR_ADMIN.getUrl());
                return remindVO;
            } else {
                //电子合同余额不足20份，请联系管理员及时充值。
                remindVO.setContent(EsignRemindEnum.BALANCE_WARNING_FOR_STAFF.getContent());
                return remindVO;
            }
        }

        return remindVO;
    }

    @Override
    public EsignCorpInfoVO getEsignCorpInfo(String corpid) throws XbbException {
        EsignCorpInfoVO esignCorpInfoVO = null;
        try {
            esignCorpInfoVO = esignHelp.getEsignCorpInfo(corpid);
        } catch (XbbException e) {
            esignCorpInfoVO = new EsignCorpInfoVO();
            esignCorpInfoVO.setIsRealName(false);
        }
        return esignCorpInfoVO;
    }

    @Override
    public EsignCorpInfoVO getEsignUserInfo(String corpid, String userId) throws XbbException {
        EsignCorpInfoVO esignUserInfoVO = null;
        try {
            esignUserInfoVO = esignHelp.getEsignUserInfo(corpid, userId);
        } catch (XbbException e) {
            e.printStackTrace();
            esignUserInfoVO = new EsignCorpInfoVO();
            esignUserInfoVO.setIsRealName(false);
        }
        return esignUserInfoVO;
    }

    @Override
    public EsignCorpRealnameVO getEsignCorpRealname(EsignCorpRealnameDTO esignCorpRealnameDTO) throws XbbException {
        return esignHelp.getEsignCorpRealname(esignCorpRealnameDTO.getCorpid(), esignCorpRealnameDTO.getUserId(), esignCorpRealnameDTO.getRedirectUrl());
    }

    @Override
    public EsignCorpRealnameVO getEsignUserRealname(EsignCorpRealnameDTO esignCorpRealnameDTO) throws XbbException {
        return esignHelp.getEsignUserRealname(esignCorpRealnameDTO.getCorpid(), esignCorpRealnameDTO.getUserId(), esignCorpRealnameDTO.getRedirectUrl());
    }

    @Override
    public BaseVO setSwitch(EsignSetSwitchDTO esignSetSwitchDTO) throws XbbException {
        String corpid = esignSetSwitchDTO.getCorpid();
        Long formId = esignSetSwitchDTO.getFormId();
        EsignSetEntity esignSet = esignSetModel.getByFormId(corpid, formId);

        if (Objects.isNull(esignSet)) {
            esignSet = new EsignSetEntity();
            esignSet.setCorpid(corpid);
            esignSet.setFormId(formId);
        }
        esignSet.setEnable(esignSetSwitchDTO.getEnable());
        esignSetModel.save(esignSet);
        return new BaseVO();
    }

    @Override
    public EsignGetSwitchVO getSwitch(EsignGetSwitchDTO esignGetSwitchDTO) throws XbbException {

        EsignSetEntity esignSetEntity = esignSetModel.getByFormId(esignGetSwitchDTO.getCorpid(), esignGetSwitchDTO.getFormId());

        Integer enable = null;
        if (Objects.isNull(esignSetEntity)) {
            enable = 0;
        } else {
            enable = esignSetEntity.getEnable();
        }
        EsignGetSwitchVO esignGetSwitchVO = new EsignGetSwitchVO();
        esignGetSwitchVO.setEnable(enable);
        return esignGetSwitchVO;
    }

    @Override
    public EsignContractMarginVO getEsignContractMargin(String corpid) throws XbbException {

        EsignContractMarginVO esignContractMarginVO = new EsignContractMarginVO();
        Integer count = 0;
        try {
            count = esignHelp.getEsignContractMargin(corpid);
        } catch (XbbException e) {
            //获取余量失败时，返回0，不做处理
        }

        esignContractMarginVO.setCount(count);
        return esignContractMarginVO;
    }

    @Override
    public EsignCorpConsoleVO getEsignCorpConsole(String corpid) throws XbbException {
        return esignHelp.getEsignCorpConsole(corpid);
    }

    @Override
    public EsignFlowStatusVO getEsignFlowStatus(EsignFlowStatusDTO esignFlowStatusDTO) throws XbbException {
        return esignHelp.getEsignFlowStatus(esignFlowStatusDTO);
    }

    @Override
    public EsignFlowDetailVO getEsignFlowDetail(EsignFlowDetailDTO esignFlowDetailDTO) throws XbbException {
        return esignHelp.getEsignFlowDetail(esignFlowDetailDTO);
    }

    @Override
    public HasEsignVO hasEsign(HasEsignDTO hasEsignDTO) throws XbbException {
        String corpid = hasEsignDTO.getCorpid();
        Long formId = hasEsignDTO.getFormId();

        HasEsignVO hasEsignVO = new HasEsignVO();
        Integer enable = 0;
        PaasAppEntity paasApp = paasAppModel.getByAlias(SystemAppMenuEnum.ESIGN.getAlias(), corpid);
        if (Objects.isNull(paasApp) || Objects.equals(paasApp.getEnable(), 0)) {
            hasEsignVO.setEnable(enable);
            return hasEsignVO;
        }

        PaasFormEntityExt paasForm = paasFormModel.getByKey(formId, corpid);

        if (Objects.isNull(paasForm)) {
            hasEsignVO.setEnable(enable);
            return hasEsignVO;
        }

        Integer saasMark = paasForm.getSaasMark();
        Integer businessType = paasForm.getBusinessType();

        if (Objects.equals(saasMark, SaasMarkEnum.PAAS.getCode())) {
            enable = 1;
        } else {
            if (Objects.equals(businessType, XbbRefTypeEnum.CONTRACT.getCode()) ||
                    Objects.equals(businessType, XbbRefTypeEnum.PURCHASE.getCode()) ||
                    Objects.equals(businessType, XbbRefTypeEnum.QUOTATION.getCode())) {
                enable = 1;
            }
        }

        hasEsignVO.setEnable(enable);
        return hasEsignVO;
    }

    @Override
    public EsignFileDetailVO getEsignFileDetail(XbbFileDetailDTO xbbFileDetailDTO) throws XbbException {
        return esignHelp.getEsignFileDetail(xbbFileDetailDTO);
    }

    @Override
    public EsignPreCheckVO checkRealname(BaseDTO baseDTO) throws XbbException {
        String corpid = baseDTO.getCorpid();
        String userId = baseDTO.getUserId();
        EsignPreCheckVO esignPreCheckVO = null;
        //企业是否实名
        EsignCorpInfoVO esignCorpInfoVO = getEsignCorpInfo(corpid);
        if (!esignCorpInfoVO.getIsRealName()) {
            esignPreCheckVO = new EsignPreCheckVO();
            esignPreCheckVO.setCode(SystemErrorCodeEnum.API_ERROR_100097.getCode());
            esignPreCheckVO.setContent(SystemErrorCodeEnum.API_ERROR_100097.getMsg());
            return esignPreCheckVO;
        }

        //个人是否实名
        EsignCorpInfoVO esignUserInfoVO = getEsignUserInfo(corpid, userId);
        if (!esignUserInfoVO.getIsRealName()) {
            esignPreCheckVO = new EsignPreCheckVO();
            esignPreCheckVO.setCode(SystemErrorCodeEnum.API_ERROR_100098.getCode());
            esignPreCheckVO.setContent(SystemErrorCodeEnum.API_ERROR_100098.getMsg());
            EsignCorpRealnameDTO esignCorpRealnameDTO = new EsignCorpRealnameDTO();
            BeanUtil.copyProperties(baseDTO, esignCorpRealnameDTO);
            EsignCorpRealnameVO esignUserRealnameVO = getEsignUserRealname(esignCorpRealnameDTO);

            esignPreCheckVO.setPcUrl(esignUserRealnameVO.getPcUrl());
            esignPreCheckVO.setMobileUrl(esignUserRealnameVO.getMobileUrl());
            return esignPreCheckVO;
        }
        return esignPreCheckVO;
    }

    @Override
    public EsignPreCheckVO preCheck(EsignPreCheckDTO esignPreCheckDTO) throws XbbException {

        //判断数据是否存在
        PaasFormEntityExt paasForm = paasFormModel.getByKey(esignPreCheckDTO.getFormId(), esignPreCheckDTO.getCorpid());
        Integer businessType = paasForm.getBusinessType();
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);

        PaasFormDataEntityExt paasFormData = null;
        switch (xbbRefTypeEnum) {
            case CONTRACT:
                paasFormData = contractModel.getByKey(esignPreCheckDTO.getDataId(), esignPreCheckDTO.getCorpid());
                break;
            case PURCHASE:
                paasFormData = purchaseModel.getByKey(esignPreCheckDTO.getDataId(), esignPreCheckDTO.getCorpid());
                break;
            case QUOTATION:
                paasFormData = quotationModel.getByKey(esignPreCheckDTO.getDataId(), esignPreCheckDTO.getCorpid());
                break;
            default:
                paasFormData = paasFormDataModel.getByKey(esignPreCheckDTO.getDataId(), esignPreCheckDTO.getCorpid());
                break;
        }

        if (Objects.isNull(paasFormData) || !Objects.equals(paasFormData.getDel(), DelEnum.NORMAL.getDel())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
        }

        EsignPreCheckVO esignPreCheckVO = checkRealname(esignPreCheckDTO);
        if (Objects.nonNull(esignPreCheckVO)) {
            return esignPreCheckVO;
        }

        //判断当前余量
        EsignContractMarginVO esignContractMarginVO = getEsignContractMargin(esignPreCheckDTO.getCorpid());
        if (Objects.equals(esignContractMarginVO.getCount(), BasicConstant.ZERO)) {
            esignPreCheckVO = new EsignPreCheckVO();
            esignPreCheckVO.setCode(SystemErrorCodeEnum.API_ERROR_100100.getCode());
            esignPreCheckVO.setContent(SystemErrorCodeEnum.API_ERROR_100100.getMsg());
            if (esignPreCheckDTO.getLoginUser().isAdminOrBoss()) {
                esignPreCheckVO.setCode(SystemErrorCodeEnum.API_ERROR_100099.getCode());
                esignPreCheckVO.setContent(SystemErrorCodeEnum.API_ERROR_100099.getMsg());
                esignPreCheckVO.setPcUrl(EsignRemindEnum.BALANCE_EMPTY_FOR_ADMIN.getUrl());
                if (Objects.equals(esignPreCheckDTO.getPlatform(), PlatFormEnum.DINGTALK.getValue())) {
                    esignPreCheckVO.setCode(SystemErrorCodeEnum.API_ERROR_100101.getCode());
                    esignPreCheckVO.setContent(SystemErrorCodeEnum.API_ERROR_100101.getMsg());
                    esignPreCheckVO.setPcUrl(null);
                }
            }
            return esignPreCheckVO;
        }

        //判断当前文件是否已经在签署中或签署完成
        EsignFlowStatusDTO esignFlowStatusDTO = new EsignFlowStatusDTO();
        BeanUtil.copyProperties(esignPreCheckDTO, esignFlowStatusDTO);
        EsignFlowStatusVO esignFlowStatusVO = getEsignFlowStatus(esignFlowStatusDTO);
        if (Objects.equals(esignFlowStatusVO.getCode(), EsignFlowStatusEnum.SIGNING.getCode()) ||
                Objects.equals(esignFlowStatusVO.getCode(), EsignFlowStatusEnum.COMPLETE.getCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100103);
        }
        return esignPreCheckVO;
    }

    @Override
    public EsignProcessStartVO getEsignProcessStart(XbbProcessStartDTO xbbProcessStartDTO) throws XbbException {


        String corpid = xbbProcessStartDTO.getCorpid();
        String userId = xbbProcessStartDTO.getUserId();

        Long formId = xbbProcessStartDTO.getFormId();
        Long dataId = xbbProcessStartDTO.getDataId();
        List<EsignFilePojo> files = getFiles(corpid, formId, dataId);
        if (files.isEmpty()) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, "文件不存在");
        }

        EsignProcessStartDTO esignProcessStartDTO = new EsignProcessStartDTO();
        esignProcessStartDTO.setInitiatorCorpId(corpid);
        esignProcessStartDTO.setInitiatorUserId(userId);
        esignProcessStartDTO.setFiles(files);

        EsignProcessStartVO esignProcessStartVO = esignHelp.getEsignProcessStart(esignProcessStartDTO);

        EsignTaskEntity esignTask = new EsignTaskEntity();
        esignTask.setCorpid(corpid);
        esignTask.setFormId(formId);
        esignTask.setDataId(dataId);
        esignTask.setTaskId(esignProcessStartVO.getTaskId());
        esignTask.setFileName("");
        esignTask.setType(EsignTaskTypeEnum.SIGN.getCode());
        esignTaskModel.insert(esignTask);

        return esignProcessStartVO;
    }

    @Override
    public EsignNoticeUrlVO signNoticeUrl(XbbSignNoticeUrlDTO xbbSignNoticeUrlDTO) throws XbbException {
        return esignHelp.signNoticeUrl(xbbSignNoticeUrlDTO);
    }

    private List<EsignFilePojo> getFiles(String corpid, Long formId, Long dataId) {
        EsignTaskEntity esignTaskEntity = esignTaskModel.getByFormId(corpid, EsignTaskTypeEnum.FILE.getCode(), formId, dataId);
        List<EsignFilePojo> files = new ArrayList<>();
        if (Objects.nonNull(esignTaskEntity)) {
            EsignFilePojo esignFilePojo = new EsignFilePojo();
            esignFilePojo.setFileId(esignTaskEntity.getTaskId());
            esignFilePojo.setFileName(esignTaskEntity.getFileName());
            files.add(esignFilePojo);
        }
        return files;
    }
}
